package network.handlers;

import java.io.IOException;

import state.Globals;
import state.group.ElevatorStruct;

import managers.ElevatorManager;
import messages.BaseMessage;
import messages.elevator.ElevatorStatusMessage;
import messages.registration.ElevatorRegistrationMessageAck;
import network.BaseModeHandler;
import network.ConnectionMode;
import network.server.ModeHandlerThread;

public class ElevatorModeHandler extends BaseModeHandler {
    
    private int failCount = 0;

    public ElevatorModeHandler(ModeHandlerThread parent)
    {
        super(parent);
    }

    @Override
    public ConnectionMode handleMessage(BaseMessage message)
    {
        if (message == null)
        {
            if (++failCount == 3)
            {
                return ConnectionMode.Closed;
            }
            else
            {
                return ConnectionMode.Elevator;
            }
        }
        
        switch (message.getMessageType())
        {
            case ElevatorStatusMessage:
                failCount = 0;
                ElevatorStatusMessage eleMess = (ElevatorStatusMessage) message;
                ElevatorStruct status = eleMess.getElevatorStruct();

                ElevatorManager.getInstance().updateStatus(parent, status);
                
                return ConnectionMode.Elevator;
            case DeregistrationMessage:
                failCount = 0;
                return ConnectionMode.Closed;
            default:
                if (++failCount == 3)
                {
                    return ConnectionMode.Closed;
                }
                else
                {
                    return ConnectionMode.Elevator;
                }
        }
    }

    @Override
    public ConnectionMode getMode()
    {
        return ConnectionMode.Elevator;
    }

    @Override
    public boolean enterMode(byte id)
    {
        
        if (id == 0)
        {
            id = ElevatorManager.getInstance().getNewId();
        }
        
        boolean result = ElevatorManager.getInstance().registerThreadHandlerForId(id, parent);
        
        if (!result)
        {
            id = -1;
        }
        
        byte maxFloors = ElevatorManager.getInstance().getDispatcherState().maxFloors;
        
        ElevatorRegistrationMessageAck ackMessage = new ElevatorRegistrationMessageAck(id, maxFloors);
        
        byte[] outBuffer = ackMessage.toByteArray();
        
        try
        {
            parent.getRemoteSocket().getOutputStream().write(outBuffer);
        }
        catch (IOException e)
        {
            Globals.getLogger().error("Error encountered while sending registration ack to elevator", e);
        }
        
        if (id != -1)
        {
        	Thread.currentThread().setName("Elevator Handler " + id);
        	
        	return true;
        }
        
        return false;
    }

    @Override
    public void exitMode()
    {
        ElevatorManager.getInstance().removeThreadHandler(parent);
    }

}
